package com.itmake.webflux.security.filter;

import cn.hutool.core.text.CharSequenceUtil;
import com.itmake.webflux.security.model.bo.JwtUserBo;
import com.itmake.webflux.security.service.TokenService;
import com.itmake.webflux.security.constant.TokenConstant;
import com.itmake.webflux.security.property.SecurityProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextImpl;
import org.springframework.security.web.server.context.ServerSecurityContextRepository;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Objects;

/**
 * Jwt 过滤器
 *
 * @author Amjacks
 * @since 2023/08/10
 */
@Component
public class JwtFilter implements ServerSecurityContextRepository {

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SecurityProperty securityProperty;

    @Override
    public Mono<Void> save(ServerWebExchange exchange, SecurityContext context) {
        return Mono.empty();
    }

    @Override
    public Mono<SecurityContext> load(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        if (CharSequenceUtil.isNotEmpty(tokenService.getToken(request))) {
            // 开启认证
            if (securityProperty.getEnable().equals(Boolean.TRUE)) {
                // 验证缓存
                if (!securityProperty.getVerifyCache().equals(Boolean.TRUE) || tokenService.verifyCache(request).equals(Boolean.TRUE)) {
                    // 验证有效性
                    String verify = tokenService.verify(request);
                    // 生成新的
                    if (Objects.nonNull(verify)) {
                        exchange.getResponse().getHeaders().set(TokenConstant.HEADER, verify);
                    }
                } else {
                    return Mono.empty();
                }
            }

            // 生成用户上下文
            JwtUserBo jwtUserBo = tokenService.getUser(request);
            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(jwtUserBo, null, jwtUserBo.getAuthorities());
            return Mono.just(authenticationToken).map(SecurityContextImpl::new);
        }
        return Mono.empty();
    }
}
